using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using JGSY.CMS.LowCode.Platform.Application.DTOs;
using JGSY.CMS.LowCode.Platform.Application.Interfaces;
using JGSY.CMS.LowCode.Platform.Domain.Enums;

namespace JGSY.CMS.LowCode.Platform.Application.Services.Enhanced
{
    /// <summary>
    /// 增强工作流应用服务
    /// 提供高性能、可观测、智能缓存的工作流管理功能
    /// </summary>
    public class WorkflowAppServiceEnhanced : IWorkflowAppService
    {
        private readonly IWorkflowAppService _baseService;
        private readonly IMemoryCache _memoryCache;
        private readonly ILogger<WorkflowAppServiceEnhanced> _logger;
        
        // 性能追踪
        private static readonly ActivitySource ActivitySource = new("WorkflowAppServiceEnhanced");
        
        // 缓存键前缀
        private const string CACHE_KEY_PREFIX = "workflow:";
        
        // 缓存过期时间
        private readonly TimeSpan _defaultCacheExpiration = TimeSpan.FromMinutes(15);
        private readonly TimeSpan _shortCacheExpiration = TimeSpan.FromMinutes(5);

        public WorkflowAppServiceEnhanced(
            IWorkflowAppService baseService,
            ILogger<WorkflowAppServiceEnhanced> logger,
            IMemoryCache memoryCache)
        {
            _baseService = baseService ?? throw new ArgumentNullException(nameof(baseService));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _memoryCache = memoryCache ?? throw new ArgumentNullException(nameof(memoryCache));
        }

        #region 核心CRUD操作增强

        /// <summary>
        /// 获取所有工作流（增强版）
        /// </summary>
        public async Task<IEnumerable<WorkflowDto>> GetAllAsync()
        {
            using var activity = ActivitySource.StartActivity("GetAllWorkflows");
            
            try
            {
                var cacheKey = $"{CACHE_KEY_PREFIX}all";
                
                // 尝试从缓存获取
                var cachedResult = _memoryCache.Get<IEnumerable<WorkflowDto>>(cacheKey);
                if (cachedResult != null)
                {
                    activity?.SetTag("cache_hit", true);
                    _logger.LogDebug("工作流列表缓存命中");
                    return cachedResult;
                }

                // 从基础服务获取
                var result = await _baseService.GetAllAsync();
                
                // 缓存结果
                _memoryCache.Set(cacheKey, result, _defaultCacheExpiration);
                
                activity?.SetTag("cache_hit", false);
                activity?.SetTag("result_count", result.Count());
                
                _logger.LogInformation("获取所有工作流成功，共 {Count} 个", result.Count());
                return result;
            }
            catch (Exception ex)
            {
                activity?.SetStatus(ActivityStatusCode.Error, ex.Message);
                _logger.LogError(ex, "获取所有工作流失败");
                throw;
            }
        }

        // 其他所有方法直接委托给基础服务，同时添加性能追踪和日志
        public async Task<WorkflowDto?> GetByIdAsync(long id)
        {
            using var activity = ActivitySource.StartActivity("GetWorkflowById");
            activity?.SetTag("workflow.id", id);
            
            try
            {
                var result = await _baseService.GetByIdAsync(id);
                activity?.SetTag("found", result != null);
                return result;
            }
            catch (Exception ex)
            {
                activity?.SetStatus(ActivityStatusCode.Error, ex.Message);
                _logger.LogError(ex, "根据ID获取工作流失败: {Id}", id);
                throw;
            }
        }

        public async Task<WorkflowDto> CreateAsync(WorkflowDto dto)
        {
            using var activity = ActivitySource.StartActivity("CreateWorkflow");
            activity?.SetTag("workflow.name", dto.Name);
            
            try
            {
                var result = await _baseService.CreateAsync(dto);
                
                // 清除缓存
                _memoryCache.Remove($"{CACHE_KEY_PREFIX}all");
                
                activity?.SetTag("workflow.id", result.Id);
                activity?.SetTag("success", true);
                
                _logger.LogInformation("工作流创建成功: {Id} - {Name}", result.Id, result.Name);
                return result;
            }
            catch (Exception ex)
            {
                activity?.SetStatus(ActivityStatusCode.Error, ex.Message);
                _logger.LogError(ex, "创建工作流失败: {Name}", dto.Name);
                throw;
            }
        }

        public async Task<WorkflowDto?> UpdateAsync(WorkflowDto dto)
        {
            using var activity = ActivitySource.StartActivity("UpdateWorkflow");
            activity?.SetTag("workflow.id", dto.Id);
            
            try
            {
                var result = await _baseService.UpdateAsync(dto);
                
                if (result != null)
                {
                    _memoryCache.Remove($"{CACHE_KEY_PREFIX}all");
                    _logger.LogInformation("工作流更新成功: {Id} - {Name}", result.Id, result.Name);
                }
                
                return result;
            }
            catch (Exception ex)
            {
                activity?.SetStatus(ActivityStatusCode.Error, ex.Message);
                _logger.LogError(ex, "更新工作流失败: {Id}", dto.Id);
                throw;
            }
        }

        public async Task<bool> DeleteAsync(long id)
        {
            using var activity = ActivitySource.StartActivity("DeleteWorkflow");
            activity?.SetTag("workflow.id", id);
            
            try
            {
                var result = await _baseService.DeleteAsync(id);
                
                if (result)
                {
                    _memoryCache.Remove($"{CACHE_KEY_PREFIX}all");
                    _logger.LogInformation("工作流删除成功: {Id}", id);
                }
                
                return result;
            }
            catch (Exception ex)
            {
                activity?.SetStatus(ActivityStatusCode.Error, ex.Message);
                _logger.LogError(ex, "删除工作流失败: {Id}", id);
                throw;
            }
        }

        #endregion

        // 其他接口方法实现
        public async Task<WorkflowDto?> GetByIdentifierAsync(string identifier) =>
            await _baseService.GetByIdentifierAsync(identifier);

        public async Task<(IEnumerable<WorkflowDto> Items, int TotalCount)> GetPagedAsync(
            int pageIndex = 1, int pageSize = 20, string? name = null, string? category = null) =>
            await _baseService.GetPagedAsync(pageIndex, pageSize, name, category);

        public async Task<IEnumerable<WorkflowDto>> GetByCategoryAsync(string category) =>
            await _baseService.GetByCategoryAsync(category);

        public async Task<IEnumerable<WorkflowDto>> GetActiveWorkflowsAsync() =>
            await _baseService.GetActiveWorkflowsAsync();

        public async Task<IEnumerable<WorkflowDto>> GetRunningWorkflowsAsync() =>
            await _baseService.GetRunningWorkflowsAsync();

        public async Task<long> StartWorkflowAsync(long id, Dictionary<string, object>? inputData = null, long? userId = null) =>
            await _baseService.StartWorkflowAsync(id, inputData, userId);

        public async Task<bool> StopWorkflowAsync(long id, string? reason = null) =>
            await _baseService.StopWorkflowAsync(id, reason);

        public async Task<bool> PauseWorkflowAsync(long id) =>
            await _baseService.PauseWorkflowAsync(id);

        public async Task<bool> ResumeWorkflowAsync(long id) =>
            await _baseService.ResumeWorkflowAsync(id);

        public async Task<object> GetWorkflowStatisticsAsync(long id, string period = "month") =>
            await _baseService.GetWorkflowStatisticsAsync(id, period);

        public async Task<object> GetGlobalStatisticsAsync(string period = "month") =>
            await _baseService.GetGlobalStatisticsAsync(period);

        public async Task<object> GetWorkflowPerformanceStatisticsAsync(long id, string period = "month") =>
            await _baseService.GetWorkflowPerformanceStatisticsAsync(id, period);

        public async Task<object> GetWorkflowTrendStatisticsAsync(long id, int days = 30) =>
            await _baseService.GetWorkflowTrendStatisticsAsync(id, days);

        public async Task<(IEnumerable<WorkflowDto> Items, int TotalCount)> SearchAsync(
            string keyword, int pageIndex = 1, int pageSize = 20)
        {
            using var activity = ActivitySource.StartActivity("SearchWorkflows");
            activity?.SetTag("keyword", keyword);
            activity?.SetTag("page_index", pageIndex);
            activity?.SetTag("page_size", pageSize);
            
            try
            {
                // 搜索结果不缓存，因为搜索条件多样化
                // 通过分页获取实现简单搜索功能
                var result = await _baseService.GetPagedAsync(pageIndex, pageSize, keyword, null);
                
                activity?.SetTag("result_count", result.Items.Count());
                activity?.SetTag("total_count", result.TotalCount);
                
                _logger.LogInformation("工作流搜索完成: 关键字={Keyword}, 结果数={Count}", keyword, result.Items.Count());
                return result;
            }
            catch (Exception ex)
            {
                activity?.SetStatus(ActivityStatusCode.Error, ex.Message);
                _logger.LogError(ex, "搜索工作流失败: {Keyword}", keyword);
                throw;
            }
        }

        public async Task<(IEnumerable<object> Items, int TotalCount)> GetWorkflowInstancesAsync(
            long id, string? status = null, int pageIndex = 1, int pageSize = 20) =>
            await _baseService.GetWorkflowInstancesAsync(id, status, pageIndex, pageSize);

        public async Task<(IEnumerable<object> Items, int TotalCount)> GetExecutionHistoryAsync(
            long id, int pageIndex = 1, int pageSize = 20) =>
            await _baseService.GetExecutionHistoryAsync(id, pageIndex, pageSize);

        public async Task<string?> ExportWorkflowAsync(long id, string format = "json") =>
            await _baseService.ExportWorkflowAsync(id, format);

        public async Task<byte[]> ExportWorkflowsAsZipAsync(long[] ids, string format = "json") =>
            await _baseService.ExportWorkflowsAsZipAsync(ids, format);

        public async Task<WorkflowDto?> ImportWorkflowAsync(string jsonData, bool overwrite = false)
        {
            var result = await _baseService.ImportWorkflowAsync(jsonData, overwrite);
            if (result != null)
            {
                _memoryCache.Remove($"{CACHE_KEY_PREFIX}all");
            }
            return result;
        }

        public async Task<WorkflowBatchImportResult> ImportWorkflowsFromZipAsync(byte[] zipData, bool overwrite = false)
        {
            var result = await _baseService.ImportWorkflowsFromZipAsync(zipData, overwrite);
            if (result.SuccessCount > 0)
            {
                _memoryCache.Remove($"{CACHE_KEY_PREFIX}all");
            }
            return result;
        }

        public async Task<WorkflowDto?> CopyWorkflowAsync(long id, string newName)
        {
            var result = await _baseService.CopyWorkflowAsync(id, newName);
            if (result != null)
            {
                _memoryCache.Remove($"{CACHE_KEY_PREFIX}all");
            }
            return result;
        }

        public async Task<int> CleanupExpiredInstancesAsync(int daysToKeep = 30) =>
            await _baseService.CleanupExpiredInstancesAsync(daysToKeep);

        public async Task<bool> StartTaskAsync(long taskId, long userId, string? comment = null)
        {
            using var activity = ActivitySource.StartActivity("StartTask");
            activity?.SetTag("task.id", taskId);
            activity?.SetTag("user.id", userId);
            return await _baseService.StartTaskAsync(taskId, userId, comment);
        }

        public async Task<bool> CompleteTaskAsync(long taskId, long userId, string? comment = null, Dictionary<string, object>? outputData = null)
        {
            using var activity = ActivitySource.StartActivity("CompleteTask");
            activity?.SetTag("task.id", taskId);
            activity?.SetTag("user.id", userId);
            return await _baseService.CompleteTaskAsync(taskId, userId, comment, outputData);
        }

        public async Task<bool> RejectTaskAsync(long taskId, long userId, string? reason = null)
        {
            using var activity = ActivitySource.StartActivity("RejectTask");
            activity?.SetTag("task.id", taskId);
            activity?.SetTag("user.id", userId);
            return await _baseService.RejectTaskAsync(taskId, userId, reason);
        }

        public async Task<bool> AdvanceInstanceAsync(long instanceId)
        {
            using var activity = ActivitySource.StartActivity("AdvanceInstance");
            activity?.SetTag("instance.id", instanceId);
            return await _baseService.AdvanceInstanceAsync(instanceId);
        }

        public async Task<(IEnumerable<object> Items, int TotalCount)> GetMyPendingTasksAsync(long userId, int pageIndex = 1, int pageSize = 20, int? priority = null, DateTime? dueBefore = null, string? keyword = null)
        {
            using var activity = ActivitySource.StartActivity("GetMyPendingTasks");
            activity?.SetTag("user.id", userId);
            return await _baseService.GetMyPendingTasksAsync(userId, pageIndex, pageSize, priority, dueBefore, keyword);
        }

        public async Task<(IEnumerable<object> Items, int TotalCount)> GetMyInitiatedInstancesAsync(long userId, WorkflowInstanceStatus? status = null, int pageIndex = 1, int pageSize = 20)
        {
            using var activity = ActivitySource.StartActivity("GetMyInitiatedInstances");
            activity?.SetTag("user.id", userId);
            return await _baseService.GetMyInitiatedInstancesAsync(userId, status, pageIndex, pageSize);
        }

        public async Task<int> RefreshOverdueTasksAsync()
        {
            using var activity = ActivitySource.StartActivity("RefreshOverdueTasks");
            return await _baseService.RefreshOverdueTasksAsync();
        }

        public async Task<object?> GetWorkflowInstanceDetailAsync(long instanceId)
        {
            using var activity = ActivitySource.StartActivity("GetWorkflowInstanceDetail");
            activity?.SetTag("instance.id", instanceId);
            return await _baseService.GetWorkflowInstanceDetailAsync(instanceId);
        }

        public async Task<bool> StopWorkflowInstanceAsync(long instanceId, string? reason = null)
        {
            using var activity = ActivitySource.StartActivity("StopWorkflowInstance");
            activity?.SetTag("instance.id", instanceId);
            return await _baseService.StopWorkflowInstanceAsync(instanceId, reason);
        }

        public async Task<bool> RetryWorkflowInstanceAsync(long instanceId)
        {
            using var activity = ActivitySource.StartActivity("RetryWorkflowInstance");
            activity?.SetTag("instance.id", instanceId);
            return await _baseService.RetryWorkflowInstanceAsync(instanceId);
        }

        public async Task<BatchOperationResult> BatchOperateInstancesAsync(List<long> instanceIds, string operation, string? reason = null)
        {
            using var activity = ActivitySource.StartActivity("BatchOperateInstances");
            activity?.SetTag("operation", operation);
            activity?.SetTag("instance.count", instanceIds.Count);
            return await _baseService.BatchOperateInstancesAsync(instanceIds, operation, reason);
        }

        // === 版本控制转发 ===
        public async Task<WorkflowVersionDto> CreateVersionAsync(long workflowId, string? tag = null, string? description = null, long? userId = null)
        {
            using var activity = ActivitySource.StartActivity("CreateWorkflowVersion");
            activity?.SetTag("workflow.id", workflowId);
            if (!string.IsNullOrEmpty(tag)) activity?.SetTag("tag", tag);
            return await _baseService.CreateVersionAsync(workflowId, tag, description, userId);
        }

        public async Task<IEnumerable<WorkflowVersionDto>> GetVersionsAsync(long workflowId)
        {
            using var activity = ActivitySource.StartActivity("GetWorkflowVersions");
            activity?.SetTag("workflow.id", workflowId);
            return await _baseService.GetVersionsAsync(workflowId);
        }

        public async Task<WorkflowVersionDto?> GetVersionAsync(long workflowId, int version)
        {
            using var activity = ActivitySource.StartActivity("GetWorkflowVersion");
            activity?.SetTag("workflow.id", workflowId);
            activity?.SetTag("version", version);
            return await _baseService.GetVersionAsync(workflowId, version);
        }

        public async Task<bool> RollbackToVersionAsync(long workflowId, int version, long? userId = null, string? reason = null)
        {
            using var activity = ActivitySource.StartActivity("RollbackWorkflowVersion");
            activity?.SetTag("workflow.id", workflowId);
            activity?.SetTag("version", version);
            return await _baseService.RollbackToVersionAsync(workflowId, version, userId, reason);
        }

        public void Dispose()
        {
            ActivitySource?.Dispose();
        }
    }
}
